from flask_sqlalchemy import SQLAlchemy
from operator import attrgetter
import datetime
import hashlib

db = SQLAlchemy()


def __init__(self, **kwargs):
    for k, v in kwargs.items():
        self.__setattr__(k, v)

class User(db.Model):
    __tablename__ = 'users'
    __rel__ = ['volsHeld']

    id = db.Column(db.Integer, primary_key=True, name='userId')
    name = db.Column(db.String(8), default='用户', name='userName')
    _class = db.Column(db.Integer, default=0, name='class')
    permission = db.Column(db.SMALLINT, default=0)
    noticesId = db.Column(db.Text, default='', name='notices')
    password = db.Column(db.String(32), default='c4d038b4bed09fdb1471ef51ec3a32cd')

    volsHeld = db.relationship('Volunteer', backref='holder')

    @property
    def notices(self):
        return UserNotice.query.filter(UserNotice.id.in_(self.noticesId.split())).selects()

    __init__ = __init__

class Student(db.Model):
    __tablename__ = 'students'
    __props__ = ['inside', 'outside', 'large']
    __rel__ = ['volsSigned']

    id = db.Column(db.Integer, primary_key=True, autoincrement=False, name='stuId')
    name = db.Column(db.String(5))

    @property
    def inside(self):
        return sum(map(attrgetter('inside'), self.volsSigned))

    @property
    def outside(self):
        return sum(map(attrgetter('outside'), self.volsSigned))

    @property
    def large(self):
        return sum(map(attrgetter('large'), self.volsSigned))

    volsSigned = db.relationship('StuVol', backref='student')

    def __init__(self, id, name):
        self.id = id
        self.name = name

class Volunteer(db.Model):
    __tablename__ = 'volunteers'
    __props__ = ['nowStuCount']
    __rel__ = ['stusSigned', 'classesSigned']

    id = db.Column(db.Integer, primary_key=True, name='volId')
    name = db.Column(db.String(32), name='volName')
    desc = db.Column(db.Text, name='description')
    date = db.Column(db.Date, name='volDate')
    time = db.Column(db.Time, name='volTime')
    stuMax = db.Column(db.Integer)
    status = db.Column(db.SMALLINT)
    inside = db.Column(db.Integer, default=0)
    outside = db.Column(db.Integer, default=0)
    large = db.Column(db.Integer, default=0)
    holderId = db.Column(db.Integer, db.ForeignKey('users.userId'))

    stusSigned = db.relationship('StuVol', backref='volunteer')
    classesSigned = db.relationship('ClassVol', backref='volunteer')

    @property
    def nowStuCount(self):
        return len(self.stusSigned)

    def __init__(self, name, desc, stuMax, holderId, **kwargs):
        self.name = name
        self.desc = desc
        self.stuMax = stuMax
        self.holderId = holderId
        self.data = datetime.date.today()
        self.time = datetime.time()
        __init__(self, **kwargs)

class StuVol(db.Model):
    __tablename__ = 'stu_vols'

    id = db.Column(db.Integer, primary_key=True)
    volId = db.Column(db.Integer, db.ForeignKey('volunteers.volId'))
    stuId = db.Column(db.Integer, db.ForeignKey('students.stuId'))
    status = db.Column(db.SMALLINT, default=0)
    inside = db.Column(db.Integer, default=0)
    outside = db.Column(db.Integer, default=0)
    large = db.Column(db.Integer, default=0)
    thought = db.Column(db.Text, default='')
    picturesHash = db.Column(db.Text, default='', name='pictures')

    @property
    def pictures(self):
        ret = []
        for id, hash in enumerate(self.picturesHash.split()):
            ret.append({
                'id': id,
                'src': Picture.query.get(hash).data
            })
        return ret

    def __init__(self, volId, stuId):
        self.volId = volId
        self.stuId = stuId

class ClassVol(db.Model):
    __tablename__ = 'class_vols'
    __props__ = ['nowStuCount']

    id = db.Column(db.Integer, primary_key=True)
    volId = db.Column(db.Integer, db.ForeignKey('volunteers.volId'))
    _class = db.Column(db.Integer, name='class')
    stuMax = db.Column(db.Integer)

    @property
    def nowStuCount(self):
        return len(filter(lambda s: self._class * 100 == s.id, self.volunteer.stusSigned))

    def __init__(self, volId, _class, stuMax):
        self.volId = volId
        self._class = _class
        self.stuMax = stuMax

class UserNotice(db.Model):
    __tablename__ = 'user_notices'

    id = db.Column(db.Integer, primary_key=True, name='noticeId')
    title = db.Column(db.Text, name='noticeTitle')
    text = db.Column(db.Text, name='noticeText')
    deadtime = db.Column(db.DateTime)

    def __init__(self, title, text, deadtime):
        self.title = title
        self.text = text
        self.deadtime = deadtime

class Picture(db.Model):
    __tablename__ = 'pictures'
    md5 = db.Column(db.String(32), primary_key=True)
    data = db.Column(db.LargeBinary(length=16777216))

    def __init__(self, bytes):
        md5 = hashlib.md5()
        md5.update(bytes)
        self.md5 = md5.hexdigest()
        self.data = bytes

class Log(db.Model):
    id = db.Column(db.Integer, primary_key=True)
